package com.yupi.yupicturebackend.manager;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.yupi.yupicturebackend.config.CosClientConfig;
import com.yupi.yupicturebackend.constant.FileConstant;
import com.yupi.yupicturebackend.exception.BusinessException;
import com.yupi.yupicturebackend.exception.ErrorCode;
import com.yupi.yupicturebackend.exception.ThrowUtils;
import com.yupi.yupicturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Optional;

/**
 * 文件管理服务
 *
 * <p>提供图片上传、校验、处理等功能</p>
 * <p><strong>注意：</strong>此类已被标记为废弃，建议使用 upload 包下的模板方法优化版本</p>
 *
 * @author yupi
 * @deprecated 已废弃，改为使用 upload 包的模板方法优化
 */
@Slf4j
@Service
@Deprecated
public class FileManager {

    @Resource
    private CosClientConfig cosClientConfig;

    @Resource
    private CosManager cosManager;

    /**
     * 上传图片
     *
     * @param multipartFile    文件
     * @param uploadPathPrefix 上传路径前缀
     * @return 上传结果
     */
    public UploadPictureResult uploadPicture(MultipartFile multipartFile, String uploadPathPrefix) {
        // 1. 校验图片
        validatePicture(multipartFile);

        // 2. 生成安全的文件名和路径
        String originalFilename = Optional.ofNullable(multipartFile.getOriginalFilename())
                .orElse("unknown");
        String uploadPath = generateUploadPath(uploadPathPrefix, originalFilename);

        File tempFile = null;
        try {
            // 3. 创建临时文件并上传
            tempFile = createTempFile(multipartFile, uploadPath);
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, tempFile);

            // 4. 提取图片信息
            ImageInfo imageInfo = extractImageInfo(putObjectResult);

            // 5. 构建返回结果
            return buildUploadResult(originalFilename, tempFile, uploadPath, imageInfo);

        } catch (IOException e) {
            log.error("创建临时文件失败, uploadPath: {}", uploadPath, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, FileConstant.ERROR_UPLOAD_FAILED);
        } catch (Exception e) {
            log.error("图片上传到对象存储失败, uploadPath: {}", uploadPath, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, FileConstant.ERROR_UPLOAD_FAILED);
        } finally {
            // 6. 清理临时文件
            deleteTempFile(tempFile);
        }
    }

    /**
     * 校验图片文件
     *
     * @param multipartFile 上传的文件
     */
    private void validatePicture(MultipartFile multipartFile) {
        // 1. 校验文件是否为空
        ThrowUtils.throwIf(multipartFile == null, ErrorCode.PARAMS_ERROR, FileConstant.ERROR_FILE_EMPTY);
        ThrowUtils.throwIf(multipartFile.isEmpty(), ErrorCode.PARAMS_ERROR, FileConstant.ERROR_FILE_EMPTY);

        // 2. 校验文件大小
        long fileSize = multipartFile.getSize();
        ThrowUtils.throwIf(fileSize > FileConstant.MAX_FILE_SIZE, ErrorCode.PARAMS_ERROR, FileConstant.ERROR_FILE_TOO_LARGE);

        // 3. 校验文件名
        String originalFilename = multipartFile.getOriginalFilename();
        ThrowUtils.throwIf(StrUtil.isBlank(originalFilename), ErrorCode.PARAMS_ERROR, "文件名不能为空");

        // 4. 校验文件后缀
        String fileSuffix = FileUtil.getSuffix(originalFilename);
        ThrowUtils.throwIf(StrUtil.isBlank(fileSuffix), ErrorCode.PARAMS_ERROR, "文件格式不能为空");
        ThrowUtils.throwIf(!FileConstant.ALLOWED_IMAGE_FORMATS_SET.contains(fileSuffix.toLowerCase()),
                ErrorCode.PARAMS_ERROR, FileConstant.ERROR_INVALID_FILE_TYPE);

        // 5. 校验文件内容类型（防止恶意文件伪装）
        validateFileContentType(multipartFile);
    }

    /**
     * 校验文件内容类型
     *
     * @param multipartFile 上传的文件
     */
    private void validateFileContentType(MultipartFile multipartFile) {
        String contentType = multipartFile.getContentType();
        if (StrUtil.isNotBlank(contentType) && !contentType.startsWith("image/")) {
            log.warn("文件内容类型不匹配: {}, 文件名: {}", contentType, multipartFile.getOriginalFilename());
            throw new BusinessException(ErrorCode.PARAMS_ERROR, FileConstant.ERROR_INVALID_FILE_TYPE);
        }
    }

    /**
     * 生成上传路径
     *
     * @param uploadPathPrefix 上传路径前缀
     * @param originalFilename 原始文件名
     * @return 上传路径
     */
    private String generateUploadPath(String uploadPathPrefix, String originalFilename) {
        String uuid = RandomUtil.randomString(FileConstant.UUID_LENGTH);
        String dateStr = DateUtil.format(new Date(), FileConstant.DATE_FORMAT);
        String fileExtension = FileUtil.getSuffix(originalFilename);

        String uploadFilename = String.format("%s%s%s%s%s",
                dateStr,
                FileConstant.FILE_NAME_SEPARATOR,
                uuid,
                FileConstant.FILE_EXTENSION_SEPARATOR,
                fileExtension);

        return String.format("%s%s%s", FileConstant.PATH_SEPARATOR, uploadPathPrefix, FileConstant.PATH_SEPARATOR + uploadFilename);
    }

    /**
     * 创建临时文件
     *
     * @param multipartFile 上传的文件
     * @param uploadPath    上传路径
     * @return 临时文件
     * @throws IOException IO异常
     */
    private File createTempFile(MultipartFile multipartFile, String uploadPath) throws IOException {
        File tempFile = File.createTempFile(FileConstant.TEMP_FILE_PREFIX, FileUtil.getSuffix(uploadPath));
        multipartFile.transferTo(tempFile);
        return tempFile;
    }

    /**
     * 提取图片信息
     *
     * @param putObjectResult COS上传结果
     * @return 图片信息
     */
    private ImageInfo extractImageInfo(PutObjectResult putObjectResult) {
        ThrowUtils.throwIf(putObjectResult == null, ErrorCode.SYSTEM_ERROR, "上传结果为空");
        ThrowUtils.throwIf(putObjectResult.getCiUploadResult() == null, ErrorCode.SYSTEM_ERROR, "图片处理结果为空");
        ThrowUtils.throwIf(putObjectResult.getCiUploadResult().getOriginalInfo() == null, ErrorCode.SYSTEM_ERROR, "原图信息为空");

        return putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
    }

    /**
     * 构建上传结果
     *
     * @param originalFilename 原始文件名
     * @param file            临时文件
     * @param uploadPath      上传路径
     * @param imageInfo       图片信息
     * @return 上传结果
     */
    private UploadPictureResult buildUploadResult(String originalFilename, File file, String uploadPath, ImageInfo imageInfo) {
        // 计算宽高比
        int picWidth = imageInfo.getWidth();
        int picHeight = imageInfo.getHeight();
        double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, FileConstant.SCALE_PRECISION).doubleValue();

        // 构建结果对象
        UploadPictureResult result = new UploadPictureResult();
        result.setUrl(cosClientConfig.getHost() + uploadPath);
        result.setPicName(FileUtil.mainName(originalFilename));
        result.setPicSize(FileUtil.size(file));
        result.setPicWidth(picWidth);
        result.setPicHeight(picHeight);
        result.setPicScale(picScale);
        result.setPicFormat(imageInfo.getFormat());

        return result;
    }

    /**
     * 清理临时文件
     *
     * @param file 临时文件
     */
    private void deleteTempFile(File file) {
        if (file == null || !file.exists()) {
            return;
        }

        try {
            boolean deleteResult = file.delete();
            if (!deleteResult) {
                log.warn("临时文件删除失败: {}", file.getAbsolutePath());
            } else {
                log.debug("临时文件删除成功: {}", file.getAbsolutePath());
            }
        } catch (Exception e) {
            log.error("删除临时文件时发生异常: {}", file.getAbsolutePath(), e);
        }
    }
}